using System;
using System.Collections.Generic;
using System.Text;
using OWED.Network;
using System.Xml;

namespace OWED.Document
{
    public class ChangeTag: ChangeAtom
    {
        private XmlNode my_oldchild;
        private XmlNode my_newchild;
        private AbsolutePath my_path;
        public ChangeTag(AbsolutePath path, XmlNode oldchild, XmlNode newchild)
        {
            my_path = path;
            this.path = path;
            my_oldchild = oldchild;
            my_newchild = newchild;
        }

        public override void Apply(XmlDocument document)
        {
            XmlNode old = my_oldchild;
            XmlNode nue = my_newchild;
            if (old.OwnerDocument != document)
            {
                old = document.ImportNode(old, true);
                nue = document.ImportNode(nue, true);
            }

            XmlNode node = my_path.getNode(document);
            //assuming this is a real check, and not
            //a reference check!
            if (old.Equals(node))
            {
                node.ParentNode.ReplaceChild(nue, node);
            }
            else
            {
                throw new ChangeAtomException("Can't apply a change, the old tag was wrong");
            }
        }

        public override void Reverse(XmlDocument document)
        {
            (new ChangeTag(my_path, my_newchild, my_oldchild)).Apply(document);
        }


        public XmlNode NewNode { get { return my_newchild; } }
        public XmlNode OldNode { get { return my_oldchild; } }


        public override string Serialize()
        {
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.CreateElement("root"));
            doc.FirstChild.AppendChild(doc.CreateElement("path"));
            doc.FirstChild.FirstChild.AppendChild(doc.CreateTextNode(path.ToString()));
            doc.FirstChild.AppendChild(doc.CreateElement("newnode"));
            doc.FirstChild.ChildNodes[1].AppendChild(doc.ImportNode(my_newchild, false));
            doc.FirstChild.AppendChild(doc.CreateElement("oldnode"));
            doc.FirstChild.ChildNodes[2].AppendChild(doc.ImportNode(my_oldchild, false));



            return ChangeAtom.AtomType(this) + doc.OuterXml;
        }

        public static new ChangeAtom DeSerialize(String atom)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(atom);
            XmlNode newnode = doc.SelectSingleNode("/root/newnode").FirstChild;
            XmlNode oldnode = doc.SelectSingleNode("/root/oldnode").FirstChild;
            AbsolutePath path = new AbsolutePath(doc.SelectSingleNode("/root/path").FirstChild.Value);

            return new ChangeTag(path, oldnode, newnode);
        }
    }
}
